#require 'byebug'
#
# 这个模块用于统一命令方法，方便一起管理
#
module Aio::Device
  module Methods

    class << self
      include Aio::Ui::Verbose

      def klass=(klass)
        @@klass = klass
      end

      def klass
        @@klass
      end

      # 单独查看接口配置
      def configuration_interfaces
        cmd = CmdSwitch.configuration(klass)
        return klass.cmds_useful[cmd][:iface_config]
      end

      # 否是有config命令
      def configuration?
        cmd = CmdSwitch.configuration(klass)
        klass.cmds_useful[cmd].nil? ? false : true
      end


      # CPU 利用率百分比
      def cpu_percent
        cmd = CmdSwitch.cpu(klass)
        return klass.cmds_useful[cmd][:cpu][:minutes_5] if kind_of?(Cisco, H3C)
        return klass.cmds_useful[cmd][:cpu][:used_percent] if klass.kind_of? Maipu
      rescue Exception
        puts_error
        return ""
      end

      # Memory 利用率百分比
      def memory_percent
        cmd = CmdSwitch.memory(klass)
        return klass.cmds_useful[cmd][:memory][:used_rate] if klass.kind_of? H3C
        return klass.cmds_useful[cmd][:memory][:proc_ratio] if klass.kind_of? Cisco
        return klass.cmds_useful[cmd][:memory][:used_percent] if klass.kind_of? Maipu
      rescue Exception
        puts_error
        return ""
      end

      # IOS 版本
      def ios_version
        cmd = CmdSwitch.version(klass)
        return klass.cmds_useful[cmd][:software][:version] if kind_of?(Cisco, H3C, Maipu)
      rescue Exception
        puts_error
        return ""
      end

      # IOS 特性集
      def soft_image
        cmd = CmdSwitch.version(klass)
        return klass.cmds_useful[cmd][:software][:soft_image] if kind_of?(Cisco, Maipu)

        # H3C 不是在version中查看
      rescue Exception
        puts_error
        return ""
      end

      # 运行时间
      def uptime
        cmd = CmdSwitch.version(klass)
        return klass.cmds_useful[cmd][:software][:uptime] if kind_of?(Cisco, H3C, Maipu)
      rescue Exception
        puts_error
        return ""
      end

      # 判断温度是否有警告
      def warning_env?
        if klass.kind_of? Maipu
          return (klass.include_warning?(:mainboard_temperature) and klass.include_warning?(:cpu_temperature))
        end
        return klass.include_warning?(:cpu_status) if klass.kind_of? Cisco
      rescue Exception
        puts_error
      end


      # 判断电源是否有警告
      def warning_power?
        return klass.include_warning?(:power_status) if kind_of?(Cisco, H3C, Maipu)
      rescue Exception
        puts_error
      end

      # 判断风扇是否有警告
      def warning_fan?
        return klass.include_warning?(:fan_status) if kind_of?(Cisco, H3C, Maipu)
      rescue Exception
        puts_error
      end

      # 只判断最关键的三个信息
      def warning_interface?
        if kind_of?(Cisco, Maipu, H3C)
          tmp = klass.include_warning?(:input_errors)
          tmp = tmp or klass.include_warning(:crc)
          tmp = tmp or klass.include_warning(:output_errors)
          return tmp
        end
      rescue Exception
        puts_error
      end

      # 板卡序列号信息
      # 返回数组: [{:name, :pid, :sn, :description}]
      def inventory
        cmd = CmdSwitch.inventory(klass)
        if kind_of?(Cisco, H3C)
          keys = klass.cmds_useful[cmd][:inventory].keys
          res = []
          keys.each do |sn|
            res << klass.cmds_useful[cmd][:inventory][sn.to_sym]
          end
          return res

        elsif kind_of?(Maipu)
          md = klass.cmds_useful[cmd][:module]
          res = []
          md.each_value do |v|
            res << {
              name: v[:module], # 这里反着来
              pid:  v[:name],
              sn:   v[:sn],
              description: ''
            }
          end
          return res

        else
          return [{:name => "", :pid => "", :sn => "", :description => ""}]
        end

      rescue Exception
        puts_error
        return [{:name => "", :pid => "", :sn => "", :description => ""}]
      end

      def clock
        cmd = CmdSwitch.clock(klass)
        pool = ["time", "zone", "week", "year", "month", "day"]
        res = []
        pool.each do |key|
          res << klass.cmds_useful[cmd][:clock][key.to_sym]
        end
        return res
      rescue Exception
        puts_error
        return ["", "", "", "", "", ""]
      end

      def get_manager_ip
        return klass.manager_ip unless klass.manager_ip.nil?

        cmd = []
        cmd[0] = CmdSwitch.interface(klass)
        cmd[1] = CmdSwitch.interface_brief(klass)

        total = []
        manager = ""

        return unless kind_of?(Cisco, H3C, Maipu)

        # 如果是 show interfaces
        if klass.has_cmd?(cmd[0])
          total = klass.cmds_useful[cmd[0]][:interface]

          total.each_value do |info|
            if (info[:iface_id] == (klass.interface[:loopback] + "0")) and info[:state] =~ /(?i)up/
              manager = info[:addr]
            end
          end

          # 如果是 show ip interface brief
        elsif klass.has_cmd?(cmd[1])
          total = klass.cmds_useful[cmd[1]][:interface_brief]

          total.each_value do |info|
            # 如果有环回口,那么就直接输出
            if (info[:interface_id].downcase == klass.interface[:loopback].downcase + "0")  and (info[:status] =~ /(?i)up/)
              manager = info[:ip] 
            end
          end
        end
        return manager

      rescue Exception
        puts_error
        return ""
      end

      private

      # 判断klass是否是指定的Device类型
      def kind_of?(*type)
        type.each do |t|
          return true if klass.kind_of?(t)
        end
        return false
      end

      # 统一的错误回显
      def puts_error
        res = /`(?<method>.*)'/.match(caller[1])
        print_error "<#{res[:method]}>方法未执行成功  #{klass.class} : #{klass.device_name}"
      end

      # 对于有相同路径的cmds_useful，可以使用此方法
      # 将按照给出的设备类型返回cmds_useful
      # 方便命令的统一管理
      def type_send(*types)
        types.each do |type|
          if klass.kind_of?(type)
            yield klass.cmds_useful
          else
            next
          end
        end
      end

    end
  end
end
